package com.choudou5.spider.config;

import com.alibaba.fastjson.JSON;
import com.choudou5.solr.util.ReflectionUtil;
import com.choudou5.solr.util.exception.BizException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.*;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 功能描述：配置解析工具
 * 修改人员：haowen@lianj.com
 * 修改时间：2018-06-23 21:36
 * 修改内容：创建文件
 */
public class SpiderConfigUtil {

    private static final Logger logger = LoggerFactory.getLogger(SpiderConfigUtil.class);

    private static List<TaskBean> TASK_LIST = new ArrayList<>();

    public static void main(String[] args) {
        System.out.println(JSON.toJSONString(getTaskList()));
    }

    public static List<TaskBean> getTaskList(String type){
        checkInit();
        return TASK_LIST;
    }

    public static List<TaskBean> getTaskList(){
        checkInit();
        return TASK_LIST;
    }

    public static TaskBean getTaskBean(String taskId){
        checkInit();
        for (TaskBean taskBean : TASK_LIST) {
            if(taskId.equals(taskBean.getId()))
                return taskBean;
        }
        throw new BizException(taskId + " 爬虫不存在");
    }

    public static List<String> getImageFields(String taskId){
        TaskBean taskBean = getTaskBean(taskId);
        if(taskBean != null) {
            List<FieldBean> sqlFieldBeans = taskBean.getTable().getFields();
            List<String> fields = new ArrayList<>(3);
            for (FieldBean sqlFieldBean : sqlFieldBeans) {
                if("img".equals(sqlFieldBean.getType())){
                    fields.add(sqlFieldBean.getName());
                }
            }
            return fields;
        }
        return null;
    }


    private static void checkInit(){
        if(TASK_LIST.isEmpty())
            parserXML("conf/spider.xml");
    }

    /**
     * 解析xml文件
     * @param path
     * @return
     */
    public static void parserXML(String path) {
        InputStream is = SpiderConfigUtil.class.getClassLoader().getResourceAsStream(path);
        if(is == null){
            logger.error(path + " 文件不存在！");
            throw new RuntimeException(path + " 文件不存在！");
        }
        TASK_LIST.clear();
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = dbFactory.newDocumentBuilder();
            Document doc = builder.parse(is);
            NodeList taskList = doc.getElementsByTagName("task");
            if (taskList != null && taskList.getLength() > 0) {
                TASK_LIST.addAll(getTaskBeans(taskList));
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(path + "， 解析xml失败.", e);
        }
        logger.info("解析完毕");
    }

    private static List<TaskBean> getTaskBeans(NodeList taskList) throws InstantiationException, IllegalAccessException {
        List<TaskBean> configs = new ArrayList<>();
        if (taskList != null && taskList.getLength() > 0) {
            for (int i = 0; i < taskList.getLength(); i++) {
                TaskBean bean = new TaskBean();
                Element task = (Element) taskList.item(i);
                NamedNodeMap attrs = task.getAttributes();
                int attrLen = attrs.getLength();
                Node attr = null;
                StringBuffer sb = new StringBuffer();
                Map<String, String> attMap = new HashMap<>();
                for (int j = 0; j < attrLen; j++) {
                    attr = attrs.item(j);
                    sb.append(attr.getNodeName() + "=" + attr.getNodeValue() + " ");
                    attMap.put(attr.getNodeName(), attr.getNodeValue());
                }
//             logger.info("attrs:" + sb.toString());
                //设置task属性
                String attrVal = null;
                Field[] fields = bean.getClass().getDeclaredFields();
                for (Field field : fields) {
                    attrVal = attMap.get(field.getName());
//                    logger.info(field.getName() + "---" + field.getType().getName());
                    field.setAccessible(true);
                    if(attrVal != null) {
                        if(field.getType() == Integer.class)
                            ReflectionUtil.setField(field, bean, Integer.valueOf(attrVal));
                        else if(field.getType() == Boolean.class)
                            ReflectionUtil.setField(field, bean, Boolean.valueOf(attrVal));
                        else
                            ReflectionUtil.setField(field, bean, attrVal);
                    }
                }
                //设置 table
                NodeList sqlFieldList = task.getElementsByTagName("table");
                if (sqlFieldList != null && sqlFieldList.getLength() > 0) {
                    Element element = (Element) sqlFieldList.item(0);
                    TableBean table = new TableBean(element.getAttribute("name"));
                    table.setFields(getList(element.getElementsByTagName("field"), FieldBean.class));
                    bean.setTable(table);

                }
                //设置formParams
                NodeList formParamList = task.getElementsByTagName("formParams");
                if (formParamList != null && formParamList.getLength() > 0) {
                    Element element = (Element) formParamList.item(0);
                    bean.setFormParams(getList(element.getElementsByTagName("param"), FormParam.class));
                }

                //设置respNextReqParams
                NodeList respNextReqParams = task.getElementsByTagName("respNextReqParam");
                if (respNextReqParams != null && respNextReqParams.getLength() > 0) {
                    Element element = (Element) respNextReqParams.item(0);
                    bean.setRespNextReqParams(getList(element.getElementsByTagName("param"), RespNextReqParam.class));
                }
                configs.add(bean);
            }
        }
        return configs;
    }



    private static <B> List<B> getList(NodeList fieldList, Class<B> clssz) throws IllegalAccessException, InstantiationException {
        List<B> result = new ArrayList<>();
        for (int i = 0; i < fieldList.getLength(); i++) {
            B bean = clssz.newInstance();
            Node sqlField = fieldList.item(i);
            NamedNodeMap attrs = sqlField.getAttributes();
            int attrLen = attrs.getLength();
            Node attr = null;
            StringBuffer sb = new StringBuffer();
            Map<String, String> attMap = new HashMap<>();
            for (int j = 0; j < attrLen; j++) {
                attr = attrs.item(j);
                sb.append(attr.getNodeName() + "=" + attr.getNodeValue() + " ");
                attMap.put(attr.getNodeName(), attr.getNodeValue());
            }
            attMap.put("expr", sqlField.getTextContent());
//        logger.info("getList attrs:" + sb.toString());
            //设置SqlField属性
            String attrVal = null;
            Field[] fields = bean.getClass().getDeclaredFields();
            for (Field field : fields) {
                attrVal = attMap.get(field.getName());
                if(attrVal != null) {
                    field.setAccessible(true);
                    ReflectionUtil.setField(field, bean, attrVal);
                }
            }
            result.add(bean);
        }
        return result;
    }


}
